package fr.upmc.aladyn.onloadreflect;
import fr.upmc.aladyn.shared.ObjetNonTrans;
import fr.upmc.aladyn.shared.ObjetTrans;
import fr.upmc.aladyn.annotation.Transactionable;

/**
 * Class containing methods used to simulate basic transactions
 * 
 * @author Thierry Wong
 * @author Seyyid ahmed Ouir
 */

@Transactionable
public class MyApp {

	protected int unInt ;
	private String uneChaine;
	private ObjetTrans objetTrans;
	private ObjetNonTrans objetNonTrans;

	/**
	 * Default constructor
	 */
	public MyApp() { 
		this.unInt = 0;
		this.uneChaine = "uneChaine";
		this.objetTrans = new ObjetTrans("transactionnable", 1);
		this.objetNonTrans = new ObjetNonTrans("nonTransactionnable", 2);
	}

	/**
	 * Getter for field unInt
	 * @return current value
	 */
	public int getUnInt() {
		return unInt;
	}

	/**
	 * Setter for field unInt
	 * @param unInt value to affect 
	 */
	public void setUnInt(int unInt) {
		this.unInt = unInt;
	}

	/**
	 * Getter for field uneChaine
	 * @return current value
	 */
	public String getUneChaine() {
		return uneChaine;
	}

	/**
	 * Setter for field uneChaine
	 * @param uneChaine value to affect
	 */
	public void setUneChaine(String s) {
		uneChaine = s;
	}

	/**
	 * Getter for field objetTrans
	 * @return current Object reference
	 */
	public ObjetTrans getObjetTrans() {
		return objetTrans;
	}

	/**
	 * Setter for field objetTrans
	 * @param objetTrans new reference of Object to affect
	 */
	public void setObjetTrans(ObjetTrans o) {
		objetTrans = o;
	}

	/**
	 * Getter for field objetNonTrans
	 * @return current Object reference
	 */
	public ObjetNonTrans getObjetNonTrans() {
		return objetNonTrans;
	}

	/**
	 * Setter for field objetNonTrans
	 * @param objetNonTrans new reference of Object to affect
	 */
	public void setObjetNonTrans(ObjetNonTrans o) {
		objetNonTrans = o;
	}

	/**
	 * Method throwing an Exception to activate transaction restoration
	 * @param i an <code> int </code> value
 	 * @throws Exception 
	 */
	public void m2(int i) throws Exception {
		System.out.println("-- Throwing an exception\n");
		throw new Exception();
	}

	/**
	 * Non transactionable method. Does some modifications.
	 */
	public void m1() {
		try 
		{
			this.unInt = 10;
			this.m2(this.unInt) ;
		} 
		catch(Exception e) {}
	}

	/**
	 * Transactionable method. Does some modifications.
	 * @throws Exception
	 */
	@Transactionable
	public void m1_transactionnee() throws Exception {
		try{
			this.setUnInt(10);
			this.setUneChaine("uneAutreChaine");

			this.objetTrans.setName("transactionnable**");
			this.objetTrans.setValue(11);

			this.objetNonTrans.setName("nonTransactionnable**");
			this.objetNonTrans.setValue(22);
			this.setObjetNonTrans(
					new ObjetNonTrans("nonTransactionnable****", 2222));

			System.out.println("\n** Avant levee d'exception **");
			System.out.println(
					"** Valeur unInt: " + unInt + "\n" + 
				    "** Valeur uneChaine: " + uneChaine + "\n" + 
				    "** Valeur oT: " + objetTrans.getValue() + "\n" + 
			    	"** Valeur oNT: " + objetNonTrans.getValue() + "\n"
			);
			this.m2(this.unInt);
		}catch (Exception e){
		}
	}
	
	/**
	 * Returns the state of fields present in the class MyApp
	 */
	public String toString(){
		return 	"** Valeur unInt: " + unInt + "\n" + 
				"** Valeur uneChaine: " + uneChaine + "\n" + 
				"** Valeur oT: " + objetTrans.getValue() + "\n" + 
				"** Valeur oNT: " + objetNonTrans.getValue();
	}

	public static void main(String[] args) throws Throwable {
		MyApp p = null;
		
		System.out.println("Version dans l'esprit transaction :\n") ;
		
		p = new MyApp();
		
		System.out.println("** Etat à l'initialisation **");
		System.out.println(p.toString());
		
		p.m1_transactionnee();
		
		System.out.println("** Etat après restauration **");
		System.out.println(p.toString());
	}

}
